package com.zk.ppa.handler;

import com.zk.ppa.commom.exception.BaseException;
import com.zk.ppa.commom.exception.BaseRuntimeException;
import com.zk.ppa.commom.exception.TokenTimeOutException;
import com.zk.ppa.commom.result.Result;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.MethodParameter;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.validation.BindException;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestControllerAdvice;

import javax.servlet.http.HttpServletRequest;
import java.util.Objects;

/**
 * @author chenxiaolong
 * @since 2021年03月21日 16:43:00
 */
@RestControllerAdvice
@Slf4j
public class GlobalExcetionHandler {
    public GlobalExcetionHandler() {
    }

    @ExceptionHandler({RuntimeException.class})
    @ResponseBody
    public Result<Object> runtimeExceptionHandler(HttpServletRequest request, RuntimeException e) {
        log.info("出错的host为：{}\n调用的接口为：{}\n异常为：{} ", new Object[]{request.getRemoteHost(), request.getRequestURL(), e});
        return Result.SYSTEM_ERROR();
    }


    @ExceptionHandler({Exception.class})
    @ResponseBody
    public Result<Object> exceptionHandler(HttpServletRequest request, Exception e) {
        log.error("出现Exception 系统异常 请求方法为：[{}]调用的接口为：[{}]异常为：[{}] ", new Object[]{request.getMethod(), request.getRequestURL(), e});
        return Result.SYSTEM_ERROR();
    }

    @ExceptionHandler({BaseException.class})
    @ResponseBody
    public Result<Object> baseExceptionHandler(HttpServletRequest request, BaseException e) {
        log.error("出现BaseException 系统业务错误 请求方法为：[{}]调用的接口为：[{}] 异常为：[{}] ", new Object[]{request.getMethod(), request.getRequestURL(), e});
        return Result.FAIL(e.getMessage());
    }

    @ExceptionHandler({BaseRuntimeException.class})
    @ResponseBody
    public Result<Object> baseRuntimeExceptionHandler(HttpServletRequest request, BaseRuntimeException e) {
        log.error("BaseRuntimeException 系统业务错误 请求方法为：[{}]调用的接口为：[{}] 异常为：[{}] ", new Object[]{request.getMethod(), request.getRequestURL(), e});
        return Result.SYSTEM_ERROR().setMessage(e.getMessage());
    }

    @ExceptionHandler({MethodArgumentNotValidException.class})
    @ResponseBody
    public Result<Object> validHandler(HttpServletRequest request, MethodArgumentNotValidException e) {
        String message = ((FieldError) Objects.requireNonNull(e.getBindingResult().getFieldError())).getDefaultMessage();
        log.error("MethodArgumentNotValidException 请求方法为：[{}] 接口：[{}]请求入参校验错误:[{}]", new Object[]{request.getMethod(), request.getRequestURL(), message});
        return Result.PARAMETER_VERIFY_ERROR().setMessage(message);
    }

    @ExceptionHandler({BindException.class})
    @ResponseBody
    public Result<Object> validSpringHandler(HttpServletRequest request, BindException e) {
        String message = ((FieldError)Objects.requireNonNull(e.getBindingResult().getFieldError())).getDefaultMessage();
        log.error("BindException 请求方法为：[{}] 接口：[{}]请求入参校验错误:[{}]", new Object[]{request.getMethod(), request.getRequestURL(), message});
        return Result.PARAMETER_VERIFY_ERROR().setMessage(message);
    }

    @ExceptionHandler({TokenTimeOutException.class})
    @ResponseBody
    public Result<Object> runtimeExceptionHandler(HttpServletRequest request, TokenTimeOutException e) {
        log.info("出错的host为：{}\n调用的接口为：{}\n异常为：{} ", new Object[]{request.getRemoteHost(), request.getRequestURL(), e});
        return Result.TOKEN_TIMEOUT_EXCEPTION();
    }

    public boolean supports(MethodParameter methodParameter, Class<? extends HttpMessageConverter<?>> aClass) {
        return false;
    }
}
